package testset;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import lv.rtu.ditf.dc.document.DocumentVectorUtils;
import lv.rtu.ditf.dc.fs.DocumentCategory;
import lv.rtu.ditf.dc.fs.FileStorage;
import lv.rtu.ditf.dc.thread.CategorizationCallback;
import lv.rtu.ditf.dc.thread.CategorizationThread;
import lv.rtu.ditf.dc.url.PlainTextPageLoader;
import lv.rtu.ditf.dc.url.UnsupportedContentTypeException;

/**
 * 
 * @author Pāvels Koliškins, Edgars Matisāns
 *
 */
public class EmpiristicKNNScript implements CategorizationCallback {
    //auto, kultura, politika, sports
    //5 x category
    private static double epsilon = 0.1;
    private static String[] categoryNames = {"Auto", "Kultura", "Politika", "Sports"};
    private static String[] categoriesResources = {
         "http://www.autonews.com/apps/pbcs.dll/article?AID=/20100515/RETAIL/100519905/1422",
         "http://www.bmwblog.com/2010/02/21/audi-rs5-vs-bmw-m3-the-war-rages-on/",
         "http://green.autoblog.com/2008/03/03/the-ten-cheapest-cars-in-the-world/",
         "http://www.howstuffworks.com/engine.htm",
         "http://autos.yahoo.com/newcars/popular/thisweek.html",

         "http://gizmodo.com/5429424/avatar-review-yes-it-changed-everything-after-all",
         "http://www.louvre.fr/llv/oeuvres/detail_notice.jsp?CONTENT%3C%3Ecnt_id=10134198673226503&CURRENT_LLV_NOTICE%3C%3Ecnt_id=10134198673226503&FOLDER%3C%3Efolder_id=9852723696500816&bmLocale=en",
         "http://www.touregypt.net/construction/",
         "http://www.thephantomoftheopera-1925.com/",
         "http://www.atu2.com/",

         "http://www.foxnews.com/politics/2010/05/13/holder-admits-reading-arizonas-immigration-law-despite-slamming/",
         "http://www.politicsdaily.com/2010/05/14/college-and-career-ready-education-reformers-need-that-define/",
         "http://www.politicsdaily.com/2010/05/06/terror-suspects-would-lose-u-s-citizenship-under-senate-bill/",
         "http://www.politicsdaily.com/2010/05/13/arrests-in-times-square-bomb-probe-three-in-u-s-one-in-pakist/",
         "http://wonkroom.thinkprogress.org/2010/05/13/levin-merkley-volcker/",

         "http://www.live-tennis.com/category/Tennis-News/WTA-Estoril-Open-Agnes-Szavay-vs-Anastasija-Sevastova-live-streaming-201005030002/",
         "http://www.hockeycanada.ca/index.php/ci_id/70837/la_id/1.htm",
         "http://www.uefa.com/memberassociations/association=eng/news/newsid=1487953.html",
         "http://www.nhlpa.com/News/Headlines/C3EE030F-1A7C-4E9A-B2AE-13D9CD0F2B96/Laich-Gets-the-Call",
         "http://www.worldreviewer.com/info/2010-sporting-events-calendar.html"
    };
    
    private PrintWriter printWriter;
    private int minDocsInCategory = 0;
    private HashMap<String, Integer> resourceDocumentVector;
    private int resourceIndex; 
    private int knn;
    private LinkedHashMap<Integer, Integer> knnResults;
    
    private EmpiristicKNNScript() throws FileNotFoundException {
    	setUp();
    }
    
    private void setUp() throws FileNotFoundException {
        try {
            List<DocumentCategory> categories = FileStorage.get().getDocumentCategories();
            if (categories.size() > 0)
            	minDocsInCategory = categories.get(0).getDocuments().size();
            
            for (int i = 1; i < categories.size(); i++) {
            	int docsInCategory = categories.get(i).getDocuments().size();
            	
            	if (minDocsInCategory > docsInCategory)
            		minDocsInCategory = docsInCategory;
            }
            
            //minDocsInCategory = FileStorage.get().getTotalDocumentCount();
            
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        
        String fileResult = "C:/categorizationKNNResults_7.txt";
        printWriter = new PrintWriter(fileResult);
        knn = minDocsInCategory;
        resourceIndex = 0;
        knnResults = new LinkedHashMap<Integer, Integer>();
    }
    
    private void tearDown() {
    	try {
	    	StringBuffer stringBuffer = new StringBuffer();
	    	
	    	for (Integer knn : knnResults.keySet()) {
	    		stringBuffer.append(knn);
	            stringBuffer.append("\t");
	    		stringBuffer.append(knnResults.get(knn));
	            stringBuffer.append("\n");
	    	}
	    	
	        printWriter.write(stringBuffer.toString());
	        printWriter.close();
    	}
        catch (Exception ex) {
        	ex.printStackTrace();
        }
    }
    
    private void processDocument() throws IOException, UnsupportedContentTypeException {
    	System.out.println(String.format("Resource index %d, knn %d", resourceIndex, knn));
    	
		if (resourceDocumentVector == null) {
			String resourceLink = categoriesResources[resourceIndex]; 
			String resourceAsText = PlainTextPageLoader.loadPage(resourceLink);
			resourceDocumentVector = DocumentVectorUtils.getDocumentVector(resourceAsText);
		}
		
		CategorizationThread categorizationThread = new CategorizationThread(resourceDocumentVector, knn, epsilon);
		categorizationThread.addCategorizationListener(this);
		categorizationThread.start();
    }
    
	@Override
	public void onCategorizationComplete(Map<String, Double> categoriesSimilarities, long executionTime) {
		/*
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(resourceIndex);
        stringBuffer.append("\t");
        stringBuffer.append(knn);
        stringBuffer.append("\t");
        // all category should have equal resource count
        stringBuffer.append(categoryNames[resourceIndex % (categoriesResources.length / categoryNames.length)]);
        stringBuffer.append("\t");
        */
        
        if (categoriesSimilarities != null && categoriesSimilarities.size() > 0) {
        	String category = categoriesSimilarities.keySet().iterator().next();
        
        	// categorization succeed
        	String expectedCategory = categoryNames[resourceIndex / (categoriesResources.length / categoryNames.length)]; 
        	if (expectedCategory.equals(category)) {
        		Integer currentResult = knnResults.get(knn);
        		
        		if (currentResult == null)
        			currentResult = 1;
        		else
        			currentResult++;
        		
        		knnResults.put(knn, currentResult);
        	}
        }
        
        //printWriter.write(stringBuffer.toString());
        
        if (resourceIndex + 1 == categoriesResources.length && knn == 1) {
        	tearDown();
        	return;
        }
        else if (knn == 1) {
        	knn = minDocsInCategory;
        	resourceIndex++;
        	resourceDocumentVector = null;
        }
        else
        	knn--;
        
        try {
			processDocument();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UnsupportedContentTypeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

    public static void main(String args[]) throws Exception {
    	EmpiristicKNNScript script = new EmpiristicKNNScript();
    	script.processDocument();
    }
}
